use std::collections::HashSet;

#[derive(Debug, PartialEq, Eq)]
pub struct Dna {
    codes: Vec<char>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct Rna{
    codes: Vec<char>,
}

impl Dna {
    pub fn new(dna: &str) -> Result<Dna, usize> {
        let mut set = HashSet::new();
        set.insert('A');
        set.insert('C');
        set.insert('G');
        set.insert('T');

        let mut codes = vec![];
        for (idx, char) in dna.chars().enumerate() {
            if !set.contains(&char) {
                return Err(idx);
            }
            codes.push(char);
        }
        Ok(Dna { codes })
    }

    pub fn into_rna(self) -> Rna {
        let codes = self.codes.into_iter().map(|c| {
            match c {
                'G' => 'C',
                'C' => 'G',
                'T' => 'A',
                _ => 'U',
            }
        }).collect::<Vec<char>>();
        Rna { codes }
    }
}

impl Rna {
    pub fn new(rna: &str) -> Result<Rna, usize> {
        let mut set = HashSet::new();
        set.insert('A');
        set.insert('C');
        set.insert('G');
        set.insert('U');

        let mut codes = vec![];
        for (idx, char) in rna.chars().enumerate() {
            if !set.contains(&char) {
                return Err(idx);
            }
            codes.push(char);
        }
        Ok(Rna { codes })
    }
}


#[test]
#[ignore]
fn invalid_dna_input_at_offset() {
    let input = "ACGTUXXCTTAA";
    let output = Dna::new(input);
    let expected = Err(4);
    assert_eq!(output, expected);
}